#include "odn_scene_Scene.h"

namespace ouden
{
	namespace scene
	{
		
		//Destructor 
		ODN_Scene::~ODN_Scene()
		{
			//Delete all the scene elements
		    while (sceneelements.size())
			{
				delete sceneelements.back();
				sceneelements.pop_back();
			}
	
			//Clear the lists of scene elements and objects
			sceneelements.clear();
			sceneobjects.clear();
		}
		
		//Updates all scene elements 
		bool ODN_Scene::Update()
		{
			for (int i=0;i<sceneelements.size();i++) {
				sceneelements[i]->Update();
			}	
		}
		
		//Draws all scene elements 
		bool ODN_Scene::Draw()
		{
			for (int i=0;i<sceneelements.size();i++) {		
				sceneelements[i]->Draw();
			}
		}
		
		//Adds a new element to the scene 
		ODN_SceneElement* ODN_Scene::addElement(ODN_SceneElement* e)
		{
			//Add the new element to the array 
			sceneelements.push_back(e);
			//Return a pointer back to the element 
			return e;
		}
		
		//Adds a new object to the scene 
		ODN_SceneObject* ODN_Scene::addObject(ODN_SceneObject* b)
		{
			//Add the new object to the sceneobjects array 
			sceneobjects.push_back(b);
			//Return a pointer back to the object 
			return b;
		}
		
		//Remove an element from the scene 
		void ODN_Scene::killElement(ODN_SceneElement* e)
		{
			//Create a new iterator to store the position of the element in the array 
			std::vector<ODN_SceneElement*>::iterator index;
			//Find the element in the array 
			index = std::find(sceneelements.begin(), sceneelements.end(), e);
			
			//TODO: Possibly look into finding a different way to do this
			
			//Delete the element
			delete e;
			e = 0;  //TODO: Make sure this is working
			//Remove the entity from the array
			sceneelements.erase(index);	
		}
		
		//Allocates all scene objects into sectors for quick lookup
		bool ODN_Scene::Sectorise()
		{
			
			//TODO: Clear sectors but leave static entities
			//Clear objects from sectors
			for (int x=0;x<sectorcount[0];x++) {
				for (int y=0;y<sectorcount[1];y++) {
					sectors[x][y].objects.clear();
				}
			}
			
			//Loop through objects 
			for (int i=0;i<sceneobjects.size();i++) {
				
				//Check if the object is alive and interactive
				if (sceneobjects[i]->isAlive() && sceneobjects[i]->isInteractive()) {
					
					//Calculate the sector that the current object is in 
					int px = int(sceneobjects[i]->pos[0] / sectorsize[0]);
					int py = int(sceneobjects[i]->pos[1] / sectorsize[1]);
					
					//TODO: Check whether boundingbox is radial or total 
					//Calculate number of sectors the object spreads across
					Vector3D sector_spread = sceneobjects[i]->boundingbox / sectorsize;
					
					//TODO: Check this 
					//Loop across sector spread
					for (int x = int(px - sector_spread[0]);x < int(px + sector_spread[0]);x++) {
						for (int y = int(py - sector_spread[1]);y < int(py + sector_spread[1]);y++) {
							
							//Add the entity to the sector
							sectors[x][y].objects.push_back(sceneobjects[i]);
							
						}
					}
				}
			}
			
		}
		
		void ODN_Scene::setSectorSize(Vector3D SectorSize)		
		{
			//Store the sector size 
			sectorsize=SectorSize;
			
			//Calculate the number of sectors 
			sectorcount = this->size / sectorsize;
			
			//Resize the array of horizontal sectors 
			sectors.resize(int(sectorcount[0]));
			
			//Loop through the horizontal sectors 
			for (int i=0;i<sectors.size();i++) {
				
				//Resize the vertical sectors 
				sectors[i].resize(int(sectorcount[1]));
				
			}
			
		}
		
		std::vector<ODN_SceneObject*> ODN_Scene::getNearbyObjects(Vector3D Pos)
		{
			
			//Temporary object array 
			std::vector<ODN_SceneObject*> p;
			
			//Calculate the sector from the given position 
			int x = int(Pos[0] / sectorsize[0]);
			int y = int(Pos[1] / sectorsize[1]);
			
			//if (x >= 0 && x < sectorcount[0] && y >= 0 && y < sectorcount[1]) { 
				
				//Store the object array from the sector 
				p = sectors[x][y].objects;
				
			//}
			
			//Return the object array 
			return p;
			
		}
		
	} //namespace scene 
} //namespace ouden 
